package net.gazhi.delonix.weixin.mp.api;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.net.ssl.SSLContext;

import net.gazhi.delonix.weixin.mp.api.response.BaseResponse;

import org.apache.commons.codec.Charsets;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;

import com.google.gson.Gson;

/**
 * API 工具类
 * 
 * @author Jeffrey Lin
 *
 */
public class APIUtils {

	private static Log log = LogFactory.getLog(APIUtils.class);

	/**
	 * 创建 SSL 请求客户端对象
	 * 
	 * @return
	 */
	private static CloseableHttpClient createSSLClient() {
		try {

			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 信任所有
				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			}).build();

			SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
			return HttpClients.custom().setSSLSocketFactory(socketFactory).build();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 执行 SSL 请求(GET)
	 * 
	 * @param url
	 * @param responseClass
	 * @return
	 */
	public static final <T extends BaseResponse> T executeSSLGet(String url, Class<T> responseClass) {
		CloseableHttpClient httpClient = createSSLClient();
		if (httpClient == null) {
			return null;
		}
		HttpGet httpGet = new HttpGet(url);
		CloseableHttpResponse response = null;
		try {
			response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String str = EntityUtils.toString(entity, Charsets.UTF_8);
				Gson gson = new Gson();
				return gson.fromJson(str, responseClass);
			} else {
				log.error("Response Entity is Null: " + httpGet.getURI().getPath());
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpGet.releaseConnection();
				if (response != null) {
					response.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		log.error("Response Error: " + httpGet.getURI().getPath());
		return null;
	}

	/**
	 * 提交 post 请求
	 * 
	 * @param url
	 * @param param
	 * @param responseClass
	 * @return
	 */
	public static final <T extends BaseResponse> T executeSSLPost(String url, Map<String, Object> param, Class<T> responseClass) {
		CloseableHttpClient httpClient = createSSLClient();
		if (httpClient == null) {
			return null;
		}
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		Gson gson = new Gson();
		String paramStr = gson.toJson(param);
		httpPost.setEntity(new StringEntity(paramStr, ContentType.APPLICATION_JSON));
		try {
			response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String str = EntityUtils.toString(entity, Charsets.UTF_8);
				return gson.fromJson(str, responseClass);
			} else {
				log.error("Response Entity is Null: " + httpPost.getURI().getPath());
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpPost.releaseConnection();
				if (response != null) {
					response.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		log.error("Response Error: " + httpPost.getURI().getPath());
		return null;
	}

}
